/*
 *  cues.cpp
 *  openFrameworks
 *
 *  Created by Jonas Jongejan on 04/08/09.
 *  Copyright 2009 HalfdanJ. All rights reserved.
 *
 */

#include "cues.h"

float Cue::getCurrentAmp(float _time){
	float fadeinv = 1.0;
	if(_time < fadein){
		fadeinv = 1.0-(fadein-_time)/fadein;
	}
	if(amps.size() == 1){
		return fadeinv*amps[0].val;
	}
	else {	
		int l = -1;
		int r = -1;
		for(int i=0;i<amps.size() ;i++){
			if(amps[i].startTime <= _time){
				if(l == -1 || amps[i].startTime > amps[l].startTime){
					l = i;
				}
			}
			if(amps[i].startTime > _time){
				if(r == -1 || amps[i].startTime < amps[r].startTime){
					r = i;
				}
			}
		}
		if(l != -1 && r != -1){
			float di = amps[r].startTime  - amps[l].startTime;
			float pos = _time - amps[l].startTime;
			float p = (float) pos / di;
			return fadeinv*(amps[l].val*(1.0-p) +  amps[r].val*(p));
		} else if(l != -1){
			return fadeinv*(amps[l].val);

		}
	}
	return 0;
}


accControlCue::accControlCue(float _time, int _layer){
	startTime = _time;
	layer = _layer;
	type = Cue::accControl;
}

void accControlCue::doStuff(float time,ofSoundPlayer * sound, int * duskValues){
	float amp = getCurrentAmp(time-startTime)/100.0;
	if(*masterOn){
		if(dusk){
			for(int i=0;i<affects.size();i++){	
				duskValues[affects[i]] *= 1.0-(1.0-*level)*amp;
			}
		} 
		if(audio){
			sound->setVolume((log(1.0-(1.0-*level*1.0)*amp)+2.0)/2.0);		
		}
	}
	//	cout<<(log(1.0-(1.0-*level*1.0)*amp)+2.0)/2.0<<"   "<<(log(1.0-(1.0-*level*1.0)*amp)+2.0)/2.0<<endl;
}


randomCue::randomCue(float _time, int _layer){
	startTime = _time;
	layer = _layer;
	type = Cue::random;
}


void randomCue::doStuff(float time,ofSoundPlayer * sound, int * duskValues){
	float amp = getCurrentAmp(time-startTime)/100.0;
	for(int i=0;i<affects.size();i++){
		if(seldom){
			if(p[i] == 0){
				if(ofRandom(0, 500) < seldomrate){
					p[i] += 0.01;
				} else {
				}
			} else {
				p[i] += 0.05 * speed;
				duskValues[affects[i]] += ((sin(p[i]-HALF_PI)+1.0)/2.0)*amp*250;
				if(p[i] > TWO_PI){
					p[i] = 0;	
				}
				if(duskValues[affects[i]] < 50)
					duskValues[affects[i]] = 0;
			}
		} else if(soft) {
			float t = ofGetElapsedTimeMillis()/(1.0/speed*1000.0)+i*210;
			duskValues[affects[i]] += ((sin(t)+1.0)/2.0)*amp*250;
			if(duskValues[affects[i]] < 50)
				duskValues[affects[i]] = 0;
		} else {
			duskValues[affects[i]] += (ofRandom(0,254))*amp;	
			if(duskValues[affects[i]] < 50)
				duskValues[affects[i]] = 0;
		}
	}
	
}

duskFileCue::duskFileCue(float _time, int _layer){
	startTime = _time;
	loop = false;
	layer = _layer;
	type = Cue::duskFile;
}


void duskFileCue::doStuff(float time,ofSoundPlayer * sound, int * duskValues){
	//cout<<"yay "<<time<<endl;
	float amp = getCurrentAmp(time-startTime)/100.0;
	float t = (time-startTime)*1000.0;
	file->pushTag("dusks", 0);
	while(file->getValue("timelinelength", 100.0, 0) < t){
		if(loop){
			t -= file->getValue("timelinelength", 100.0, 0);
		} else {
			t = file->getValue("timelinelength", 100.0, 0);
		}
	}

	for(int i=0;i<affects.size();i++){
		file->pushTag("timeline", 0);
		int numChannels =  file->getNumTags("channel");
		for(int u=0;u<numChannels;u++){
			if(file->getAttribute("channel", "number", 0, u) == i){
				file->pushTag("channel", u);
				int numKeys = file->getNumTags("key");
				for(int k=0;k<numKeys-1;k++){
					if(t > file->getAttribute("key","time",0.0,k) && t < file->getAttribute("key","time",0.0,k+1)){
						float t1 = file->getAttribute("key","time",0.0,k);
						float t2 = file->getAttribute("key","time",0.0,k+1);
						float p = (t-t1)/(t2-t1);
						float add = amp*(file->getAttribute("key","val",0.0,k)*(1.0-p) + file->getAttribute("key","val",0.0,k+1)*p);
						if(!isnan(add)){
							duskValues[affects[i]] += add;
						}
					}
				}
				file->popTag();
			}
		}
	//	cout<<duskValues[13]<<endl;
		file->popTag();
		/*	if(!soft)
		 duskValues[affects[i]] += (ofRandom(0,160))*amp;
		 else {
		 duskValues[i] = amp*((sin(ofGetElapsedTimeMillis()/1000.0+i*210)+1.0)/2.0)*120.0;
		 }*/
	}
	file->popTag();

	
}

noneCue::noneCue(float _time,  int _layer){
	startTime = _time;
	type = Cue::none;
	layer = _layer;
}

